{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Seaborn 地毯图 (rugplot) 完整教程\n",
    "\n",
    "本教程详细讲解 Seaborn 中地毯图的使用方法，包括基础绘图、样式定制以及与其他分布图的组合使用。\n",
    "\n",
    "## 目录\n",
    "1. 基础地毯图\n",
    "2. 样式定制\n",
    "3. 与直方图组合\n",
    "4. 与核密度估计组合\n",
    "5. 分组展示\n",
    "6. 综合应用"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import seaborn as sns\n",
    "import matplotlib.pyplot as plt\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "\n",
    "# 设置样式\n",
    "sns.set_theme(style=\"whitegrid\")\n",
    "plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']\n",
    "plt.rcParams['axes.unicode_minus'] = False\n",
    "\n",
    "# 加载示例数据\n",
    "penguins = sns.load_dataset(\"penguins\")\n",
    "tips = sns.load_dataset(\"tips\")\n",
    "iris = sns.load_dataset(\"iris\")\n",
    "\n",
    "print(\"企鹅数据集预览：\")\n",
    "penguins.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "## 1. 基础地毯图\n",
    "\n",
    "### 1.1 什么是地毯图（Rug Plot）？\n",
    "\n",
    "**地毯图**是一种简单的单变量数据可视化方法，在坐标轴上用短线标记每个数据点的位置。\n",
    "\n",
    "**特点**：\n",
    "- 显示数据的精确位置\n",
    "- 展示数据密度\n",
    "- 识别聚类和间隙\n",
    "- 通常与其他分布图组合使用"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.figure(figsize=(10, 3))\n",
    "sns.rugplot(data=penguins, x=\"flipper_length_mm\")\n",
    "plt.title(\"基础地毯图：企鹅鳍长度\", fontsize=14)\n",
    "plt.xlabel(\"鳍长度 (mm)\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1.2 地毯图的作用\n",
    "\n",
    "从地毯图中可以观察到：\n",
    "- **数据分布**：线条密集的地方数据点多\n",
    "- **聚类**：明显的数据群组\n",
    "- **间隙**：数据稀疏的区域\n",
    "- **异常值**：孤立的数据点"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 使用较小数据集更清晰\n",
    "sample_data = penguins['flipper_length_mm'].dropna().sample(50, random_state=42)\n",
    "\n",
    "plt.figure(figsize=(10, 3))\n",
    "sns.rugplot(data=sample_data)\n",
    "plt.title(\"地毯图示例（50个样本）\", fontsize=14)\n",
    "plt.xlabel(\"鳍长度 (mm)\")\n",
    "plt.show()\n",
    "\n",
    "print(\"观察：每条竖线代表一个数据点\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "## 2. 样式定制\n",
    "\n",
    "### 2.1 调整线条高度和宽度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fig, axes = plt.subplots(3, 1, figsize=(10, 8))\n",
    "\n",
    "# 默认样式\n",
    "sns.rugplot(data=penguins, x=\"flipper_length_mm\", ax=axes[0])\n",
    "axes[0].set_title(\"默认样式\")\n",
    "\n",
    "# 调整高度\n",
    "sns.rugplot(data=penguins, x=\"flipper_length_mm\", height=0.1, ax=axes[1])\n",
    "axes[1].set_title(\"height=0.1 (更高的线条)\")\n",
    "\n",
    "# 调整线宽\n",
    "sns.rugplot(data=penguins, x=\"flipper_length_mm\", linewidth=2, ax=axes[2])\n",
    "axes[2].set_title(\"linewidth=2 (更粗的线条)\")\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.2 颜色和透明度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fig, axes = plt.subplots(2, 1, figsize=(10, 6))\n",
    "\n",
    "# 自定义颜色\n",
    "sns.rugplot(data=penguins, x=\"flipper_length_mm\", \n",
    "            color='red', linewidth=1.5, ax=axes[0])\n",
    "axes[0].set_title(\"自定义颜色\")\n",
    "\n",
    "# 调整透明度（处理重叠）\n",
    "sns.rugplot(data=penguins, x=\"flipper_length_mm\", \n",
    "            alpha=0.3, ax=axes[1])\n",
    "axes[1].set_title(\"alpha=0.3 (透明度，可看出密度)\")\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "## 3. 与直方图组合\n",
    "\n",
    "### 3.1 基础组合\n",
    "\n",
    "地毯图最常见的用法是与其他分布图组合，提供数据点的精确位置信息。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.figure(figsize=(10, 6))\n",
    "sns.histplot(data=penguins, x=\"flipper_length_mm\", bins=20)\n",
    "sns.rugplot(data=penguins, x=\"flipper_length_mm\", color='red', alpha=0.5)\n",
    "plt.title(\"直方图 + 地毯图\", fontsize=14)\n",
    "plt.xlabel(\"鳍长度 (mm)\")\n",
    "plt.ylabel(\"频数\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.2 不同位置的地毯图\n",
    "\n",
    "可以通过调整坐标轴将地毯图放在不同位置。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fig, axes = plt.subplots(2, 1, figsize=(10, 8))\n",
    "\n",
    "# 地毯图在底部\n",
    "sns.histplot(data=penguins, x=\"flipper_length_mm\", bins=20, ax=axes[0])\n",
    "sns.rugplot(data=penguins, x=\"flipper_length_mm\", \n",
    "            color='red', alpha=0.5, ax=axes[0])\n",
    "axes[0].set_title(\"地毯图在底部\")\n",
    "\n",
    "# 地毯图在顶部（通过 height 负值）\n",
    "sns.histplot(data=penguins, x=\"flipper_length_mm\", bins=20, ax=axes[1])\n",
    "sns.rugplot(data=penguins, x=\"flipper_length_mm\", \n",
    "            color='red', alpha=0.5, height=-0.03, ax=axes[1])\n",
    "axes[1].set_title(\"地毯图在顶部 (height=-0.03)\")\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "## 4. 与核密度估计组合\n",
    "\n",
    "### 4.1 KDE + 地毯图"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.figure(figsize=(10, 6))\n",
    "sns.kdeplot(data=penguins, x=\"flipper_length_mm\", fill=True, alpha=0.5)\n",
    "sns.rugplot(data=penguins, x=\"flipper_length_mm\", color='black', alpha=0.3)\n",
    "plt.title(\"核密度估计 + 地毯图\", fontsize=14)\n",
    "plt.xlabel(\"鳍长度 (mm)\")\n",
    "plt.ylabel(\"密度\")\n",
    "plt.show()\n",
    "\n",
    "print(\"优势：KDE 显示平滑趋势，地毯图显示实际数据点位置\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4.2 多层组合"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.figure(figsize=(12, 6))\n",
    "\n",
    "# 直方图\n",
    "sns.histplot(data=penguins, x=\"flipper_length_mm\", \n",
    "             stat='density', bins=20, alpha=0.3, color='gray')\n",
    "\n",
    "# KDE\n",
    "sns.kdeplot(data=penguins, x=\"flipper_length_mm\", \n",
    "            color='blue', linewidth=2)\n",
    "\n",
    "# 地毯图\n",
    "sns.rugplot(data=penguins, x=\"flipper_length_mm\", \n",
    "            color='red', alpha=0.5, height=0.05)\n",
    "\n",
    "plt.title(\"三层组合：直方图 + KDE + 地毯图\", fontsize=14)\n",
    "plt.xlabel(\"鳍长度 (mm)\")\n",
    "plt.ylabel(\"密度\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "## 5. 分组展示\n",
    "\n",
    "### 5.1 使用 hue 分组"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.figure(figsize=(10, 6))\n",
    "sns.kdeplot(data=penguins, x=\"flipper_length_mm\", \n",
    "            hue=\"species\", fill=True, alpha=0.3)\n",
    "sns.rugplot(data=penguins, x=\"flipper_length_mm\", \n",
    "            hue=\"species\", alpha=0.5)\n",
    "plt.title(\"分组 KDE + 地毯图\", fontsize=14)\n",
    "plt.xlabel(\"鳍长度 (mm)\")\n",
    "plt.ylabel(\"密度\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5.2 分组地毯图的高度调整\n",
    "\n",
    "当有多个组时，可以通过调整高度避免重叠。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fig, ax = plt.subplots(figsize=(12, 6))\n",
    "\n",
    "# 绘制 KDE\n",
    "sns.kdeplot(data=penguins, x=\"flipper_length_mm\", \n",
    "            hue=\"species\", fill=True, alpha=0.3, ax=ax)\n",
    "\n",
    "# 为每个物种绘制不同高度的地毯图\n",
    "species_list = penguins['species'].unique()\n",
    "colors = ['C0', 'C1', 'C2']\n",
    "heights = [0.02, 0.04, 0.06]\n",
    "\n",
    "for species, color, height in zip(species_list, colors, heights):\n",
    "    data = penguins[penguins['species'] == species]\n",
    "    sns.rugplot(data=data, x=\"flipper_length_mm\", \n",
    "                color=color, alpha=0.6, height=height, ax=ax)\n",
    "\n",
    "plt.title(\"分层地毯图（不同高度避免重叠）\", fontsize=14)\n",
    "plt.xlabel(\"鳍长度 (mm)\")\n",
    "plt.ylabel(\"密度\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "## 6. 综合应用\n",
    "\n",
    "### 6.1 完整示例：餐厅小费分析"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fig, axes = plt.subplots(2, 2, figsize=(14, 10))\n",
    "\n",
    "# 1. 直方图 + 地毯图\n",
    "sns.histplot(data=tips, x=\"total_bill\", bins=20, ax=axes[0, 0])\n",
    "sns.rugplot(data=tips, x=\"total_bill\", color='red', alpha=0.3, ax=axes[0, 0])\n",
    "axes[0, 0].set_title(\"直方图 + 地毯图\")\n",
    "\n",
    "# 2. KDE + 地毯图\n",
    "sns.kdeplot(data=tips, x=\"total_bill\", fill=True, ax=axes[0, 1])\n",
    "sns.rugplot(data=tips, x=\"total_bill\", color='black', alpha=0.3, ax=axes[0, 1])\n",
    "axes[0, 1].set_title(\"KDE + 地毯图\")\n",
    "\n",
    "# 3. 分组 KDE + 地毯图\n",
    "sns.kdeplot(data=tips, x=\"total_bill\", hue=\"time\", \n",
    "            fill=True, alpha=0.3, ax=axes[1, 0])\n",
    "sns.rugplot(data=tips, x=\"total_bill\", hue=\"time\", \n",
    "            alpha=0.5, ax=axes[1, 0])\n",
    "axes[1, 0].set_title(\"分组 KDE + 地毯图\")\n",
    "\n",
    "# 4. 完整组合\n",
    "sns.histplot(data=tips, x=\"total_bill\", stat='density', \n",
    "             bins=20, alpha=0.3, ax=axes[1, 1])\n",
    "sns.kdeplot(data=tips, x=\"total_bill\", color='blue', \n",
    "            linewidth=2, ax=axes[1, 1])\n",
    "sns.rugplot(data=tips, x=\"total_bill\", color='red', \n",
    "            alpha=0.3, height=0.05, ax=axes[1, 1])\n",
    "axes[1, 1].set_title(\"完整组合\")\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6.2 双变量地毯图"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.figure(figsize=(10, 8))\n",
    "\n",
    "# 散点图\n",
    "sns.scatterplot(data=penguins, x=\"flipper_length_mm\", y=\"body_mass_g\", \n",
    "                hue=\"species\", alpha=0.6, s=50)\n",
    "\n",
    "# x 轴地毯图\n",
    "sns.rugplot(data=penguins, x=\"flipper_length_mm\", \n",
    "            hue=\"species\", alpha=0.3, height=0.03)\n",
    "\n",
    "# y 轴地毯图\n",
    "sns.rugplot(data=penguins, y=\"body_mass_g\", \n",
    "            hue=\"species\", alpha=0.3, height=0.03)\n",
    "\n",
    "plt.title(\"双变量散点图 + 地毯图\", fontsize=14)\n",
    "plt.xlabel(\"鳍长度 (mm)\")\n",
    "plt.ylabel(\"体重 (g)\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6.3 小样本数据展示"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 对于小样本，地毯图特别有用\n",
    "small_sample = tips.sample(30, random_state=42)\n",
    "\n",
    "fig, axes = plt.subplots(2, 1, figsize=(10, 8))\n",
    "\n",
    "# 只有 KDE（可能过度平滑）\n",
    "sns.kdeplot(data=small_sample, x=\"total_bill\", fill=True, ax=axes[0])\n",
    "axes[0].set_title(\"小样本：只有 KDE（可能误导）\")\n",
    "\n",
    "# KDE + 地毯图（显示实际数据点）\n",
    "sns.kdeplot(data=small_sample, x=\"total_bill\", fill=True, ax=axes[1])\n",
    "sns.rugplot(data=small_sample, x=\"total_bill\", \n",
    "            color='red', alpha=0.8, height=0.05, ax=axes[1])\n",
    "axes[1].set_title(\"小样本：KDE + 地毯图（显示真实数据点）\")\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()\n",
    "\n",
    "print(f\"样本量：{len(small_sample)}\")\n",
    "print(\"地毯图帮助我们看到实际只有30个数据点\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6.4 异常值检测"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.figure(figsize=(12, 6))\n",
    "\n",
    "# 绘制分布\n",
    "sns.histplot(data=tips, x=\"total_bill\", bins=30, alpha=0.5)\n",
    "sns.kdeplot(data=tips, x=\"total_bill\", color='blue', linewidth=2)\n",
    "sns.rugplot(data=tips, x=\"total_bill\", color='red', alpha=0.5, height=0.05)\n",
    "\n",
    "# 标记可能的异常值\n",
    "q1 = tips['total_bill'].quantile(0.25)\n",
    "q3 = tips['total_bill'].quantile(0.75)\n",
    "iqr = q3 - q1\n",
    "lower_bound = q1 - 1.5 * iqr\n",
    "upper_bound = q3 + 1.5 * iqr\n",
    "\n",
    "plt.axvline(upper_bound, color='green', linestyle='--', \n",
    "            label=f'异常值阈值: ${upper_bound:.2f}')\n",
    "\n",
    "outliers = tips[tips['total_bill'] > upper_bound]\n",
    "plt.scatter(outliers['total_bill'], [0] * len(outliers), \n",
    "            color='orange', s=100, zorder=5, label=f'异常值 ({len(outliers)}个)')\n",
    "\n",
    "plt.title(\"使用地毯图辅助异常值检测\", fontsize=14)\n",
    "plt.xlabel(\"账单总额 ($)\")\n",
    "plt.ylabel(\"频数\")\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 总结\n",
    "\n",
    "### 地毯图的优势\n",
    "\n",
    "1. **显示精确位置**：每个数据点的确切位置\n",
    "2. **补充信息**：与其他图表组合使用效果最佳\n",
    "3. **识别模式**：聚类、间隙、异常值\n",
    "4. **小样本友好**：避免过度解读平滑曲线\n",
    "\n",
    "### 参数调整指南\n",
    "\n",
    "1. **height**：\n",
    "   - 默认值通常合适\n",
    "   - 与其他图组合时可能需要调整\n",
    "   - 负值可将地毯图放在顶部\n",
    "\n",
    "2. **alpha（透明度）**：\n",
    "   - 数据量大：0.2-0.4\n",
    "   - 数据量小：0.6-0.8\n",
    "\n",
    "3. **linewidth**：\n",
    "   - 数据量大：1-1.5\n",
    "   - 数据量小：1.5-2\n",
    "\n",
    "### 使用场景\n",
    "\n",
    "**适合使用地毯图**：\n",
    "- 小到中等样本量（<500）\n",
    "- 与 KDE 或直方图组合\n",
    "- 需要显示精确数据点位置\n",
    "- 异常值检测\n",
    "- 展示数据聚类\n",
    "\n",
    "**不适合地毯图**：\n",
    "- 大数据集（>1000）：线条过于密集\n",
    "- 单独使用：信息量有限\n",
    "- 离散数据：可能重叠严重\n",
    "\n",
    "### 最佳实践\n",
    "\n",
    "1. **总是与其他图组合**：\n",
    "   - 直方图 + 地毯图\n",
    "   - KDE + 地毯图\n",
    "   - 散点图 + 地毯图\n",
    "\n",
    "2. **调整透明度**：\n",
    "   - 数据量大时降低透明度\n",
    "   - 避免遮挡主图\n",
    "\n",
    "3. **分组时注意**：\n",
    "   - 使用不同高度避免重叠\n",
    "   - 或使用透明度区分\n",
    "\n",
    "4. **小样本数据**：\n",
    "   - 地毯图特别有价值\n",
    "   - 防止过度解读平滑曲线\n",
    "\n",
    "### 与其他分布图的对比\n",
    "\n",
    "| 图表类型 | 优势 | 劣势 |\n",
    "|---------|------|------|\n",
    "| 直方图 | 清晰的频数统计 | 受区间划分影响 |\n",
    "| KDE | 平滑连续 | 可能过度平滑 |\n",
    "| ECDF | 精确累积信息 | 不直观展示密度 |\n",
    "| 地毯图 | 精确位置 | 大数据集不适用 |\n",
    "\n",
    "**结论**：地毯图是优秀的辅助工具，与其他分布图组合使用效果最佳。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
